{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Deep Learning Models -- A collection of various deep learning architectures, models, and tips for TensorFlow and PyTorch in Jupyter Notebooks.\n",
    "- Author: Sebastian Raschka\n",
    "- GitHub Repository: https://github.com/rasbt/deeplearning-models"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Sebastian Raschka \n",
      "\n",
      "CPython 3.6.1\n",
      "IPython 6.0.0\n",
      "\n",
      "tensorflow 1.2.0\n"
     ]
    }
   ],
   "source": [
    "%load_ext watermark\n",
    "%watermark -a 'Sebastian Raschka' -v -p tensorflow"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Model Zoo -- Convolutional General Adversarial Networks"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Implementation of General Adversarial Nets (GAN) where both the discriminator and generator have convolutional and deconvolutional layers, respectively. In this example, the GAN generator was trained to generate MNIST images.\n",
    "\n",
    "Uses\n",
    "\n",
    "- samples from a random normal distribution (range [-1, 1])\n",
    "- dropout\n",
    "- leaky relus\n",
    "- batch normalization\n",
    "- separate batches for \"fake\" and \"real\" images (where the labels are 1 = real images, 0 = fake images)\n",
    "- MNIST images normalized to [-1, 1] range\n",
    "- generator with tanh output\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'/gpu:0'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from tensorflow.examples.tutorials.mnist import input_data\n",
    "import pickle as pkl\n",
    "\n",
    "tf.test.gpu_device_name()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Extracting MNIST_data/train-images-idx3-ubyte.gz\n",
      "Extracting MNIST_data/train-labels-idx1-ubyte.gz\n",
      "Extracting MNIST_data/t10k-images-idx3-ubyte.gz\n",
      "Extracting MNIST_data/t10k-labels-idx1-ubyte.gz\n"
     ]
    }
   ],
   "source": [
    "### Abbreviatiuons\n",
    "# dis_*: discriminator network\n",
    "# gen_*: generator network\n",
    "\n",
    "########################\n",
    "### Helper functions\n",
    "########################\n",
    "\n",
    "def leaky_relu(x, alpha=0.0001):\n",
    "    return tf.maximum(alpha * x, x)\n",
    "\n",
    "\n",
    "########################\n",
    "### DATASET\n",
    "########################\n",
    "\n",
    "mnist = input_data.read_data_sets('MNIST_data')\n",
    "\n",
    "\n",
    "#########################\n",
    "### SETTINGS\n",
    "#########################\n",
    "\n",
    "# Hyperparameters\n",
    "learning_rate = 0.001\n",
    "training_epochs = 50\n",
    "batch_size = 64\n",
    "dropout_rate = 0.5\n",
    "\n",
    "# Architecture\n",
    "dis_input_size = 784\n",
    "gen_input_size = 100\n",
    "\n",
    "# Other settings\n",
    "print_interval = 200\n",
    "\n",
    "#########################\n",
    "### GRAPH DEFINITION\n",
    "#########################\n",
    "\n",
    "g = tf.Graph()\n",
    "with g.as_default():\n",
    "    \n",
    "    # Placeholders for settings\n",
    "    dropout = tf.placeholder(tf.float32, shape=None, name='dropout')\n",
    "    is_training = tf.placeholder(tf.bool, shape=None, name='is_training')\n",
    "    \n",
    "    # Input data\n",
    "    dis_x = tf.placeholder(tf.float32, shape=[None, dis_input_size],\n",
    "                           name='discriminator_inputs')     \n",
    "    gen_x = tf.placeholder(tf.float32, [None, gen_input_size],\n",
    "                           name='generator_inputs')\n",
    "\n",
    "\n",
    "    ##################\n",
    "    # Generator Model\n",
    "    ##################\n",
    "\n",
    "    with tf.variable_scope('generator'):\n",
    "        \n",
    "        # 100 => 784 => 7x7x64\n",
    "        gen_fc = tf.layers.dense(inputs=gen_x, units=3136,\n",
    "                                 bias_initializer=None, # no bias required when using batch_norm\n",
    "                                 activation=None)\n",
    "        gen_fc = tf.layers.batch_normalization(gen_fc, training=is_training)\n",
    "        gen_fc = leaky_relu(gen_fc)\n",
    "        gen_fc = tf.reshape(gen_fc, (-1, 7, 7, 64))\n",
    "        \n",
    "        # 7x7x64 => 14x14x32\n",
    "        deconv1 = tf.layers.conv2d_transpose(gen_fc, filters=32, \n",
    "                                             kernel_size=(3, 3), strides=(2, 2), \n",
    "                                             padding='same',\n",
    "                                             bias_initializer=None,\n",
    "                                             activation=None)\n",
    "        deconv1 = tf.layers.batch_normalization(deconv1, training=is_training)\n",
    "        deconv1 = leaky_relu(deconv1)     \n",
    "        deconv1 = tf.layers.dropout(deconv1, rate=dropout_rate)\n",
    "        \n",
    "        # 14x14x32 => 28x28x16\n",
    "        deconv2 = tf.layers.conv2d_transpose(deconv1, filters=16, \n",
    "                                             kernel_size=(3, 3), strides=(2, 2), \n",
    "                                             padding='same',\n",
    "                                             bias_initializer=None,\n",
    "                                             activation=None)\n",
    "        deconv2 = tf.layers.batch_normalization(deconv2, training=is_training)\n",
    "        deconv2 = leaky_relu(deconv2)     \n",
    "        deconv2 = tf.layers.dropout(deconv2, rate=dropout_rate)\n",
    "        \n",
    "        # 28x28x16 => 28x28x8\n",
    "        deconv3 = tf.layers.conv2d_transpose(deconv2, filters=8, \n",
    "                                             kernel_size=(3, 3), strides=(1, 1), \n",
    "                                             padding='same',\n",
    "                                             bias_initializer=None,\n",
    "                                             activation=None)\n",
    "        deconv3 = tf.layers.batch_normalization(deconv3, training=is_training)\n",
    "        deconv3 = leaky_relu(deconv3)     \n",
    "        deconv3 = tf.layers.dropout(deconv3, rate=dropout_rate)\n",
    "        \n",
    "        # 28x28x8 => 28x28x1\n",
    "        gen_logits = tf.layers.conv2d_transpose(deconv3, filters=1, \n",
    "                                                kernel_size=(3, 3), strides=(1, 1), \n",
    "                                                padding='same',\n",
    "                                                bias_initializer=None,\n",
    "                                                activation=None)\n",
    "        gen_out = tf.tanh(gen_logits, 'generator_outputs')\n",
    "\n",
    "\n",
    "    ######################\n",
    "    # Discriminator Model\n",
    "    ######################\n",
    "    \n",
    "    def build_discriminator_graph(input_x, reuse=None):\n",
    "\n",
    "        with tf.variable_scope('discriminator', reuse=reuse):\n",
    "            \n",
    "            # 28x28x1 => 14x14x8\n",
    "            conv_input = tf.reshape(input_x, (-1, 28, 28, 1))\n",
    "            conv1 = tf.layers.conv2d(conv_input, filters=8, kernel_size=(3, 3),\n",
    "                                     strides=(2, 2), padding='same',\n",
    "                                     bias_initializer=None,\n",
    "                                     activation=None)\n",
    "            conv1 = tf.layers.batch_normalization(conv1, training=is_training)\n",
    "            conv1 = leaky_relu(conv1)\n",
    "            conv1 = tf.layers.dropout(conv1, rate=dropout_rate)\n",
    "            \n",
    "            # 14x14x8 => 7x7x32\n",
    "            conv2 = tf.layers.conv2d(conv1, filters=32, kernel_size=(3, 3),\n",
    "                                     strides=(2, 2), padding='same',\n",
    "                                     bias_initializer=None,\n",
    "                                     activation=None)\n",
    "            conv2 = tf.layers.batch_normalization(conv2, training=is_training)\n",
    "            conv2 = leaky_relu(conv2)\n",
    "            conv2 = tf.layers.dropout(conv2, rate=dropout_rate)\n",
    "\n",
    "            # fully connected layer\n",
    "            fc_input = tf.reshape(conv2, (-1, 7*7*32))\n",
    "            logits = tf.layers.dense(inputs=fc_input, units=1, activation=None)\n",
    "            out = tf.sigmoid(logits)\n",
    "            \n",
    "        return logits, out    \n",
    "\n",
    "    # Create a discriminator for real data and a discriminator for fake data\n",
    "    dis_real_logits, dis_real_out = build_discriminator_graph(dis_x, reuse=False)\n",
    "    dis_fake_logits, dis_fake_out = build_discriminator_graph(gen_out, reuse=True)\n",
    "\n",
    "\n",
    "    #####################################\n",
    "    # Generator and Discriminator Losses\n",
    "    #####################################\n",
    "    \n",
    "    # Two discriminator cost components: loss on real data + loss on fake data\n",
    "    # Real data has class label 0, fake data has class label 1\n",
    "    dis_real_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=dis_real_logits, \n",
    "                                                            labels=tf.zeros_like(dis_real_logits))\n",
    "    dis_fake_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=dis_fake_logits, \n",
    "                                                            labels=tf.ones_like(dis_fake_logits))\n",
    "    dis_cost = tf.add(tf.reduce_mean(dis_fake_loss), \n",
    "                      tf.reduce_mean(dis_real_loss), \n",
    "                      name='discriminator_cost')\n",
    " \n",
    "    # Generator cost: difference between dis. prediction and label \"0\" for real images\n",
    "    gen_loss = tf.nn.sigmoid_cross_entropy_with_logits(logits=dis_fake_logits,\n",
    "                                                       labels=tf.zeros_like(dis_fake_logits))\n",
    "    gen_cost = tf.reduce_mean(gen_loss, name='generator_cost')\n",
    "    \n",
    "    \n",
    "    #########################################\n",
    "    # Generator and Discriminator Optimizers\n",
    "    #########################################\n",
    "      \n",
    "    dis_optimizer = tf.train.AdamOptimizer(learning_rate)\n",
    "    dis_train_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='discriminator')\n",
    "    dis_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope='discriminator')\n",
    "    \n",
    "    with tf.control_dependencies(dis_update_ops): # required to upd. batch_norm params\n",
    "        dis_train = dis_optimizer.minimize(dis_cost, var_list=dis_train_vars,\n",
    "                                           name='train_discriminator')\n",
    "    \n",
    "    gen_optimizer = tf.train.AdamOptimizer(learning_rate)\n",
    "    gen_train_vars = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='generator')\n",
    "    gen_update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope='generator')\n",
    "    \n",
    "    with tf.control_dependencies(gen_update_ops): # required to upd. batch_norm params\n",
    "        gen_train = gen_optimizer.minimize(gen_cost, var_list=gen_train_vars,\n",
    "                                           name='train_generator')\n",
    "    \n",
    "    # Saver to save session for reuse\n",
    "    saver = tf.train.Saver()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Minibatch: 0001 | Dis/Gen Cost:    1.657/0.917\n",
      "Minibatch: 0201 | Dis/Gen Cost:    0.776/1.551\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.827/1.839\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.438/2.190\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.583/0.872\n",
      "Epoch:     0001 | Dis/Gen AvgCost: 0.934/1.593\n",
      "Minibatch: 0001 | Dis/Gen Cost:    0.634/1.577\n",
      "Minibatch: 0201 | Dis/Gen Cost:    0.598/2.277\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.763/1.207\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.524/2.216\n",
      "Minibatch: 0801 | Dis/Gen Cost:    0.252/2.839\n",
      "Epoch:     0002 | Dis/Gen AvgCost: 0.789/1.668\n",
      "Minibatch: 0001 | Dis/Gen Cost:    0.726/1.502\n",
      "Minibatch: 0201 | Dis/Gen Cost:    0.634/1.563\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.956/1.716\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.882/1.410\n",
      "Minibatch: 0801 | Dis/Gen Cost:    0.861/1.835\n",
      "Epoch:     0003 | Dis/Gen AvgCost: 0.783/1.663\n",
      "Minibatch: 0001 | Dis/Gen Cost:    0.732/1.914\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.240/1.239\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.047/1.460\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.749/1.630\n",
      "Minibatch: 0801 | Dis/Gen Cost:    0.883/1.536\n",
      "Epoch:     0004 | Dis/Gen AvgCost: 0.880/1.611\n",
      "Minibatch: 0001 | Dis/Gen Cost:    0.726/1.820\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.143/1.496\n",
      "Minibatch: 0401 | Dis/Gen Cost:    0.925/1.249\n",
      "Minibatch: 0601 | Dis/Gen Cost:    0.839/1.300\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.318/0.955\n",
      "Epoch:     0005 | Dis/Gen AvgCost: 1.018/1.426\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.047/1.319\n",
      "Minibatch: 0201 | Dis/Gen Cost:    0.982/1.724\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.723/0.943\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.036/1.284\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.543/0.896\n",
      "Epoch:     0006 | Dis/Gen AvgCost: 1.175/1.231\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.128/1.209\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.045/1.154\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.449/0.896\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.116/1.281\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.380/0.949\n",
      "Epoch:     0007 | Dis/Gen AvgCost: 1.244/1.107\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.292/0.929\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.295/0.918\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.271/0.998\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.078/1.300\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.371/1.022\n",
      "Epoch:     0008 | Dis/Gen AvgCost: 1.261/1.044\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.352/1.008\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.763/0.743\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.040/1.291\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.334/1.050\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.214/1.039\n",
      "Epoch:     0009 | Dis/Gen AvgCost: 1.283/1.015\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.628/0.699\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.204/1.033\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.393/0.891\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.176/1.043\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.493/0.765\n",
      "Epoch:     0010 | Dis/Gen AvgCost: 1.297/0.980\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.421/0.793\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.453/0.898\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.090/1.107\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.412/0.927\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.319/0.813\n",
      "Epoch:     0011 | Dis/Gen AvgCost: 1.309/0.944\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.347/1.046\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.255/1.034\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.205/0.926\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.191/0.935\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.450/0.762\n",
      "Epoch:     0012 | Dis/Gen AvgCost: 1.305/0.943\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.375/0.727\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.361/1.070\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.020/0.943\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.250/0.921\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.461/0.996\n",
      "Epoch:     0013 | Dis/Gen AvgCost: 1.303/0.927\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.258/0.765\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.177/1.066\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.175/0.970\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.213/0.845\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.433/0.846\n",
      "Epoch:     0014 | Dis/Gen AvgCost: 1.305/0.920\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.654/0.708\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.437/0.770\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.487/0.740\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.167/1.100\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.342/0.854\n",
      "Epoch:     0015 | Dis/Gen AvgCost: 1.319/0.893\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.356/0.826\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.161/1.101\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.355/0.878\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.281/1.022\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.198/0.828\n",
      "Epoch:     0016 | Dis/Gen AvgCost: 1.320/0.887\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.197/0.808\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.337/0.922\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.223/0.934\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.376/0.734\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.334/0.806\n",
      "Epoch:     0017 | Dis/Gen AvgCost: 1.338/0.865\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.352/0.790\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.391/0.910\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.329/0.776\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.445/0.681\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.301/0.840\n",
      "Epoch:     0018 | Dis/Gen AvgCost: 1.335/0.842\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.377/0.781\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.277/0.872\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.351/0.767\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.501/0.657\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.343/0.797\n",
      "Epoch:     0019 | Dis/Gen AvgCost: 1.331/0.850\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.429/0.756\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.341/0.840\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.447/0.768\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.284/0.909\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.212/1.033\n",
      "Epoch:     0020 | Dis/Gen AvgCost: 1.342/0.843\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.332/0.827\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.570/0.884\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.455/0.659\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.275/0.705\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.288/0.851\n",
      "Epoch:     0021 | Dis/Gen AvgCost: 1.343/0.832\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.233/0.942\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.375/0.816\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.256/0.852\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.320/0.970\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.159/1.066\n",
      "Epoch:     0022 | Dis/Gen AvgCost: 1.349/0.834\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.429/0.885\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.643/0.703\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.471/0.893\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.407/0.775\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.364/0.728\n",
      "Epoch:     0023 | Dis/Gen AvgCost: 1.331/0.850\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.492/0.734\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.354/0.808\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.280/0.938\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.545/0.723\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.326/0.814\n",
      "Epoch:     0024 | Dis/Gen AvgCost: 1.355/0.818\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.293/0.903\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.456/0.688\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.466/0.781\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.157/0.831\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.445/0.715\n",
      "Epoch:     0025 | Dis/Gen AvgCost: 1.350/0.811\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.500/0.735\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.589/0.799\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.429/0.675\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.329/0.673\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.318/0.856\n",
      "Epoch:     0026 | Dis/Gen AvgCost: 1.348/0.808\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.207/0.994\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.404/0.758\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.410/0.788\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.284/0.861\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.397/0.760\n",
      "Epoch:     0027 | Dis/Gen AvgCost: 1.349/0.798\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.277/0.772\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.252/0.962\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.340/0.709\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.322/0.947\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.389/0.839\n",
      "Epoch:     0028 | Dis/Gen AvgCost: 1.347/0.807\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.485/0.634\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.213/0.865\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.316/0.836\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.405/0.751\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.453/0.704\n",
      "Epoch:     0029 | Dis/Gen AvgCost: 1.350/0.801\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.294/0.776\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.321/0.800\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.447/0.693\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.305/0.809\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.502/0.622\n",
      "Epoch:     0030 | Dis/Gen AvgCost: 1.355/0.787\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.369/0.679\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.406/0.774\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.424/0.804\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.410/0.703\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.273/0.876\n",
      "Epoch:     0031 | Dis/Gen AvgCost: 1.347/0.796\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.426/0.701\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.494/0.801\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.317/0.771\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.404/0.819\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.413/0.766\n",
      "Epoch:     0032 | Dis/Gen AvgCost: 1.357/0.792\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.348/0.782\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.336/0.759\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.470/0.683\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.445/0.734\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.332/0.863\n",
      "Epoch:     0033 | Dis/Gen AvgCost: 1.350/0.780\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.379/0.783\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.392/0.876\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.365/0.777\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.497/0.734\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.337/0.767\n",
      "Epoch:     0034 | Dis/Gen AvgCost: 1.354/0.780\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.340/0.795\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.214/0.849\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.240/0.846\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.367/0.731\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.368/0.680\n",
      "Epoch:     0035 | Dis/Gen AvgCost: 1.351/0.786\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.221/0.897\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.242/0.850\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.291/0.792\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.264/0.818\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.418/0.774\n",
      "Epoch:     0036 | Dis/Gen AvgCost: 1.350/0.781\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.446/0.740\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.264/0.814\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.398/0.859\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.261/0.833\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.409/0.786\n",
      "Epoch:     0037 | Dis/Gen AvgCost: 1.350/0.797\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.375/0.775\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.558/0.715\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.334/0.807\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.445/0.734\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.247/0.898\n",
      "Epoch:     0038 | Dis/Gen AvgCost: 1.355/0.782\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.386/0.795\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.294/0.812\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.395/0.805\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.371/0.738\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.346/0.752\n",
      "Epoch:     0039 | Dis/Gen AvgCost: 1.346/0.784\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.313/0.776\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.300/0.861\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.459/0.692\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.310/0.822\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.410/0.757\n",
      "Epoch:     0040 | Dis/Gen AvgCost: 1.351/0.783\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.253/0.860\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.398/0.677\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.373/0.787\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.318/0.818\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.306/0.757\n",
      "Epoch:     0041 | Dis/Gen AvgCost: 1.350/0.773\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.272/0.820\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.237/0.793\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.443/0.742\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.406/0.774\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.325/0.766\n",
      "Epoch:     0042 | Dis/Gen AvgCost: 1.352/0.775\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.314/0.775\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.328/0.833\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.404/0.679\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.304/0.806\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.358/0.687\n",
      "Epoch:     0043 | Dis/Gen AvgCost: 1.352/0.775\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.467/0.737\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.378/0.694\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.370/0.798\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.244/0.857\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.349/0.827\n",
      "Epoch:     0044 | Dis/Gen AvgCost: 1.358/0.767\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.368/0.737\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.345/0.766\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.378/0.760\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.301/0.797\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.356/0.789\n",
      "Epoch:     0045 | Dis/Gen AvgCost: 1.356/0.757\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.400/0.711\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.311/0.829\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.452/0.648\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.365/0.765\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.397/0.820\n",
      "Epoch:     0046 | Dis/Gen AvgCost: 1.354/0.758\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.385/0.723\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.313/0.778\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.318/0.773\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.384/0.756\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.435/0.718\n",
      "Epoch:     0047 | Dis/Gen AvgCost: 1.351/0.771\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.308/0.739\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.384/0.739\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.339/0.755\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.339/0.801\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.408/0.822\n",
      "Epoch:     0048 | Dis/Gen AvgCost: 1.357/0.760\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.324/0.782\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.325/0.791\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.394/0.731\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.390/0.718\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.374/0.772\n",
      "Epoch:     0049 | Dis/Gen AvgCost: 1.360/0.755\n",
      "Minibatch: 0001 | Dis/Gen Cost:    1.364/0.819\n",
      "Minibatch: 0201 | Dis/Gen Cost:    1.384/0.759\n",
      "Minibatch: 0401 | Dis/Gen Cost:    1.313/0.776\n",
      "Minibatch: 0601 | Dis/Gen Cost:    1.351/0.744\n",
      "Minibatch: 0801 | Dis/Gen Cost:    1.394/0.743\n",
      "Epoch:     0050 | Dis/Gen AvgCost: 1.363/0.752\n"
     ]
    }
   ],
   "source": [
    "##########################\n",
    "### TRAINING & EVALUATION\n",
    "##########################\n",
    "\n",
    "with tf.Session(graph=g) as sess:\n",
    "    sess.run(tf.global_variables_initializer())\n",
    "    \n",
    "    avg_costs = {'discriminator': [], 'generator': []}\n",
    "\n",
    "    for epoch in range(training_epochs):\n",
    "        dis_avg_cost, gen_avg_cost = 0., 0.\n",
    "        total_batch = mnist.train.num_examples // batch_size\n",
    "\n",
    "        for i in range(total_batch):\n",
    "            \n",
    "            batch_x, batch_y = mnist.train.next_batch(batch_size)\n",
    "            batch_x = batch_x*2 - 1 # normalize\n",
    "            batch_randsample = np.random.uniform(-1, 1, size=(batch_size, gen_input_size))\n",
    "            \n",
    "            # Train\n",
    "            \n",
    "            _, dc = sess.run(['train_discriminator', 'discriminator_cost:0'],\n",
    "                             feed_dict={'discriminator_inputs:0': batch_x, \n",
    "                                        'generator_inputs:0': batch_randsample,\n",
    "                                        'dropout:0': dropout_rate,\n",
    "                                        'is_training:0': True})\n",
    "            \n",
    "            _, gc = sess.run(['train_generator', 'generator_cost:0'],\n",
    "                             feed_dict={'generator_inputs:0': batch_randsample,\n",
    "                                        'dropout:0': dropout_rate,\n",
    "                                        'is_training:0': True})\n",
    "            \n",
    "            dis_avg_cost += dc\n",
    "            gen_avg_cost += gc\n",
    "\n",
    "            if not i % print_interval:\n",
    "                print(\"Minibatch: %04d | Dis/Gen Cost:    %.3f/%.3f\" % (i + 1, dc, gc))\n",
    "                \n",
    "\n",
    "        print(\"Epoch:     %04d | Dis/Gen AvgCost: %.3f/%.3f\" % \n",
    "              (epoch + 1, dis_avg_cost / total_batch, gen_avg_cost / total_batch))\n",
    "        \n",
    "        avg_costs['discriminator'].append(dis_avg_cost / total_batch)\n",
    "        avg_costs['generator'].append(gen_avg_cost / total_batch)\n",
    "    \n",
    "    \n",
    "    saver.save(sess, save_path='./gan-conv.ckpt')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f1181618240>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "plt.plot(range(len(avg_costs['discriminator'])), \n",
    "         avg_costs['discriminator'], label='discriminator')\n",
    "plt.plot(range(len(avg_costs['generator'])),\n",
    "         avg_costs['generator'], label='generator')\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:tensorflow:Restoring parameters from ./gan-conv.ckpt\n"
     ]
    },
    {
     "data": {
      "image/png": "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\nkPFiTEREFDJejImIiELGizEREVHIeDEmIiIKGS/GREREIUvrYuyc6+ac+9o5t8A51z9TnSIiIiok\nKW/64ZyrBGAegK4AlgCYBuAsz/NmZ657RERE+W/bNL72AAALPM9bCADOuVEAegCIezGuV6+e16JF\nizQesvBMnz59darHnXG8Ky6d8QY45qngazxYHO9gJTve6VyMGwNYbP6/BECHLT/JOdcXQF8AaNas\nGUpKStJ4yMLjnFuU+LN8n8/xTkNFx7v0azjmaeBrPFgc72AlO95ZL+DyPK/Y87wiz/OK6tdPecJB\nSeJ4B49jHiyOd7A43sFI52K8FEBT8/8mpW1ERERUAelcjKcBaO2ca+mcqwzgTADjMtMtIiKiwpHy\nPWPP8zY55y4HMB5AJQBDPc/7KmM9o4Izfvx4jYcPHw4AePnll7Vt4sSJGh988MHBdYyIct6mTZsA\nADvuuKO2XXjhhRoPGjQo8D5Z6RRwwfO8NwG8maG+EBERFSTuwEVERBSytGbGROn64osvNP7ggw80\nnjlzJgBgm23K/l58882yJAzT1Lnn77//BuD/mRIF5eabbwZQ9joE/O8/YeNvBRERUch4MSYiIgoZ\n09QUuI0bN2o8atQojR988EGN//zzTwBA06ZlS9lvvPHGAHqXX/766y8AwKWXXqptl1xyicYtW7bU\nuGbNmlnti6Sn7X74zrmsPiYVtjVr1mj8zjvvACirqgaA2267LeguxcWZMRERUcg4M6bAyV+oAPD0\n009rLLNhy64trl69enY7lsPsbLNPnz4aP/fccwD82Yji4mKN7cy0f//Np6AOGDBA26pWrZrxvnI2\nvNngwYMB+GdnXbp00XjYsGEAOF7puPbaazWWYq0qVapoW4MGDQLvUzycGRMREYWMF2MiIqKQMU2d\nhpEjR2p87LHHAsh+EUw+sGnqlStXxvwcSdG1bt06iC7lvFdffVXj0aNHayzpabu216a0bXzvvfcC\n8G9L+v7772ucjZR1IbBj/Mwzz2g8duxYAMBPP/2kba+88orGkyZNAgBs2LBB2/bee+9yHyc/extm\nxIgRGsv64sMPP1zb2rZtG1zHEuDMmIiIKGS8GBMREYWMaWoA3377rcZ23aW1cOFCAECdOnW0Taoh\nAeD7778HAPTr1y8bXcwLa9euBeBPxdmt6Y4++miNzz33XACsJE1ExvSOO+7Qtl9//VXj7bffHgDQ\n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\nTFMTERGFjBdjIiKikPFiTEREFDJejImIiELGizEREVHIeDEmIiIKGS/GREREIUvrYuyc6+ac+9o5\nt8A51z9TnSIiIiokKW/64ZyrBGAegK4AlgCYBuAsz/NmZ657RERE+W/bNL72AAALPM9bCADOuVEA\negCIezGuV6+e16JFizQesvBMnz59darHnXG8Ky6d8QY45qngazxYHO9gJTve6VyMGwNYbP6/BECH\nLT/JOdcXQF8AaNasGUpKStJ4yMLjnFuU+LN8n8/xTkNFx7v0azjmaeBrPFgc72AlO95ZL+DyPK/Y\n87wiz/OK6tdPecJBSeJ4B49jHiyOd7A43sFI52K8FEBT8/8mpW1ERERUAelcjKcBaO2ca+mcqwzg\nTADjMtMtIiKiwpHyPWPP8zY55y4HMB5AJQBDPc/7KmM9IyIiKhDpFHDB87w3AbyZob4QEREVJO7A\nRUREFLK0ZsZEiWzatEnjIUOGAADsOsUjjzxS40qVKgXWL6J8Jxs6OedC7gklgzNjIiKikPFiTERE\nFDKmqSljNmzYAAA44IADtG3hwoUa//XXXwCAatWqadupp56q8RNPPJHtLuasW265ReOnn35a4/Xr\n1wMA/vjjD23beeedNb7ooosAANtuW/arfvbZZ2tsbyPI19nPpcTs/v6HHnooAGD16tXa9umnn2pc\no0aNwPrF9HRu4cyYiIgoZAXxJ7D9619mZwCwYsUKAECtWrW0bdasWRrPnTtX4//+978AgJkzZ2qb\n/Yt4m202/13TrFkzbXvhhRc0bteuXepPIEfIjGvOnDna9ueff2rcvHlzAMAuu+yibeedd15AvctN\nixZt3tb2/vvv1zY7prF89913Gt94443lPn799ddrbGdPBx98MADghhtu0Lbu3btXrMMFyI7hjjvu\nCAD44IMPtK1z584az5gxI+bXUe5Lt2COM2MiIqKQ8WJMREQUsrxOU0t6etCgQdo2ffp0jffff38A\nQPXq1bXtX//6l8Y2TZ2sb775RuPbb79d46eeegoAkG+nnkyYMEHjN9/cvBmbvRXQqVMnjSdNmgQA\n2H777QPqXe778ssvASROTafK3mp5//33AQDz5s3TtmeeeUbjrl27ZqUP+STWa1tuhwHAmjVrNK5d\nu3YgfaJgpHvbgTNjIiKikPFiTEREFLK8TlPL9oojRozQNkn7AcBzzz0HwJ+qS0SqpgF/ClZS3kuW\n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\nt7bx9yU2m02zsewV8eSTTwbep0zjzJiIiChkvBgTERGFLCfS1IUgH9JT+fAciLJpwoQJYXeBIooz\nYyIiopDxYkxERBQypqlDZKuPmeIlIipcnBkTERGFjDPjEHE2TEREAGfGREREoePFmIiIKGQu1haG\nWXsw51Zh89nH9QCsDuyBg5ON59Xc87z6iT+tPDPeQH6OeaTGG8j713i2nlMmXuP5ON5AxF7jfE9J\nSVLjHejFWB/UuRLP84oCf+Asi/LzinLfUhXl5xTlvqUqys8pyn1LR5SfV5T7lqownxPT1ERERCHj\nxZiIiChkYV2Mi0N63GyL8vOKct9SFeXnFOW+pSrKzynKfUtHlJ9XlPuWqtCeUyj3jImIiKgM09RE\nREQh48WYiIgoZLwYExERhYwXYyIiopDxYkxERBQyXoyJiIhCxosxERFRyNK6GDvnujnnvnbOLXDO\n9c9Up4iIiApJypt+OOcqAZgHoCuAJQCmATjL87zZmeseERFR/ts2ja89AMACz/MWAoBzbhSAHgDi\nXozr1avntWjRIo2HLDzTp09fnepxZxzviktnvAGOeSr4Gg8WxztYyY53OhfjxgAWm/8vAdBhy09y\nzvUF0BcAmjVrhpKSkjQesvA45xYl/izf53O801DR8S79Go55GvgaDxbHO1jJjnfWC7g8zyv2PK/I\n87yi+vVTnnBQkjjeweOYB4vjHSyOdzDSuRgvBdDU/L9JaRsRERFVQDoX42kAWjvnWjrnKgM4E8C4\nzHSLiIiocKR8z9jzvE3OucsBjAdQCcBQz/O+yljPiIiIcsSvv/4KANhxxx1T+vp0Crjged6bAN5M\n53sQEREVOu7ARUREFLK0ZsZERERhmTJlCgBg7Nix2vbyyy9r3K1bN43799+8SWTLli2z0pclS5YA\nAHbddVdtc84l/fWcGRMREYWMF2MiIqKQMU1NRESR9NtvvwEA5syZo23PPfecxk8++SQA4I8//tA2\nmxp+6623NN5rr70AAH379tW2ypUrZ6yvrVq1AgD89ddf2rbttslfYjkzJiIiChlnxpRx559/vsb2\nr9hrr70WAHDzzTdrW5UqVTSuVKlSAL2jRHbffXeNq1atqvGMGTPC6A4VmNWrV2s8bNgwAMDtt9+u\nbb/88stWv75atWoaS1EVAFx99dUA/LNVO0veZpv05qby/vXnn3+m9PWcGRMREYWMF2MiIqKQMU0d\n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\nDBkyRNts0dYVV1yhcayb+/as10Jl/8qVWawttJLDOoCyNeJ2nbEtWIm1+5DNRDz77LMa5/PM2Bad\nyPuhVqMAABzFSURBVIzYnpN96aWXavzII49k7HFlo3w7O5szZ47GK1asAODPPiUqFssHdqe9GTNm\nAPDPuOzOTeeddx4AYP/999c2OxOz5L3Ifm4hiPV7brOMdl13suxabykUBfxrvCVDIYfQAP73F1tI\nFwbOjImIiELGizEREVHIIpemtoUPidLTch6wPXjApvCqVKkCwL+u0qax7QbwsdjUoKSqbFoj3raP\nhUp+HvYc6Pvvv1/jQw45BADwr3/9S9tmzpypsU39CZsGtWuS842kgAHg8ssv11heg3fccYe23Xzz\nzRpnMk0s38v+jsQqXiq0NLUlRUDyLwBccMEFGt90000AgCVLlsT8ejue8nMuhLXFln39SErZvo7S\nPSxD1t4DZQV1APDOO++Ue3x7C6Jjx45pPW66ODMmIiIKGS/GREREIYtcmtqmDf7zn/8AAC666CJt\n++9//6uxpBXsWtVMst/XVgULOXOX/Gxl5IABAzSeN28eAOCLL77QNpuetbcoRNu2bTW+7rrrMtrP\nKJCzVW+99VZts+u0JX1nn3u2UsMvvvgiAP+tGHuL55lnngHgX71AQOvWrTWWFRh2fbZ19NFHa2xP\nayokNlUv4zV2bNnxBna717p16wKo2GtebpcB/tOzYp3d3aJFC43trYcw8LeKiIgoZLwYExERhSxy\naWpLNjw4++yztc2mOLKRLtu0aZPGNq0hKVSp0N4ypths6nn48OEAgB9//DHmx61YJ0DZWxj5Qio7\nZevXLckGCNl6rdnNbCRlbqvamzRporFsimBTsHaDhTp16mS1r1FiK3LtVqV2e0Vhq9MHDRqkcdWq\nVbPTuRwit7FuuOEGbbMbP6Vr5MiRGssWuzblfdxxx2XssdLFmTEREVHIIj0zFrYgKNs+//xzjWP9\nlWu3V5PtAyk+WdsHAC+//DKA+Ad42EyHrMHs1KlTFnsXPpkZ2LO5bQbAri/OFHtwgd3yVYpo7M/H\nrvVv165due9l14Sef/75AICnnnoqc52NGJkR2xnV3Llzt/o1dntYm2mgMpl8j7dZC3v4jLTbQq1+\n/fpl7HHTxZkxERFRyHgxJiIiCllOpKmDZE/0iHVSk03BBZk+zyU2TSRri4GyLQLtx62ioiKNH374\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f1181173400>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "####################################\n",
    "### RELOAD & GENERATE SAMPLE IMAGES\n",
    "####################################\n",
    "\n",
    "\n",
    "n_examples = 25\n",
    "\n",
    "with tf.Session(graph=g) as sess:\n",
    "    saver.restore(sess, save_path='./gan-conv.ckpt')\n",
    "\n",
    "    batch_randsample = np.random.uniform(-1, 1, size=(n_examples, gen_input_size))\n",
    "    new_examples = sess.run('generator/generator_outputs:0',\n",
    "                            feed_dict={'generator_inputs:0': batch_randsample,\n",
    "                                       'dropout:0': 0.0,\n",
    "                                       'is_training:0': False})\n",
    "\n",
    "fig, axes = plt.subplots(nrows=5, ncols=5, figsize=(8, 8),\n",
    "                         sharey=True, sharex=True)\n",
    "\n",
    "for image, ax in zip(new_examples, axes.flatten()):\n",
    "    ax.imshow(image.reshape((dis_input_size // 28, dis_input_size // 28)), cmap='binary')\n",
    "\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
